<template>
  <ProTable
    ref="tableRef"
    :fetchListApi="_listAllDevice"
    :columns="columns"
    row-key="deviceId"
    :hideLoading="hideLoading"
    :rowSelection="rowSelection"
    :onValuesChange="changeFormState"
  >
    <template #toolbars>
      <Row class="w-full mr-3">
        <Col :span="16">
          <Space>
            <b-button
              icon="gen"
              @click="handelRestart(1, '重启')"
              :disabled="!selectRows.length || isOffline"
              code="device:restart"
              >重启</b-button
            >
            <b-button
              icon="restore"
              @click="handelRestart(7, '重置')"
              :disabled="!selectRows.length || isOffline"
              code="device:restart"
              >重置</b-button
            >
            <b-button
              icon="handle"
              @click="handleConnect()"
              :disabled="!selectRows.length || isOffline"
              code="device:disconnectDevice"
              >断开</b-button
            >
            <b-button
              icon="delete"
              @click="onDelete()"
              :disabled="!selectRows.length"
              code="device:remove"
              >删除</b-button
            >
            <b-button
              icon="del"
              @click="handleClearLog()"
              :disabled="!selectRows.length"
              code="device:clearLog"
              >清空日志</b-button
            >
          </Space>
        </Col>
        <Col :span="8" class="text-right content-center"
          ><b-button icon="export" @click="onExport()" code="device:export"
            >导出</b-button
          >
        </Col>
      </Row>
    </template>
    <template #operation="{ record }">
      <b-button
        icon="config"
        type="link"
        @click="onOperate(record)"
        v-if="record.onlineStatus == 1"
        code="device:deviceEdit"
        >操作</b-button
      >
      <b-button
        icon="edit"
        type="link"
        @click="onView(record)"
        code="device:query"
        >详情</b-button
      >
      <b-button
        icon="monitor"
        type="link"
        @click="onPush(record)"
        v-if="record.onlineStatus == 1"
        code="device:drill"
        >演练</b-button
      >
      <b-button icon="data" type="link" @click="onLog(record)" code="device:log"
        >日志</b-button
      >
    </template>
  </ProTable>
  <FormModal :items="items" />
  <Modal
    title="操作配置"
    v-model:open="deviceTabsVisible"
    :width="1400"
    :mask-closable="false"
    :keyboard="false"
    :footer="null"
    centered
    destroy-on-close
    class="deviceTabsModal modal-tab-bg"
  >
    <DeviceTabs :page-data="pageData" @close="deviceTabsVisible = false" />
  </Modal>
  <!-- 详情弹窗 -->
  <Modal
    v-model:open="deviceInfoTabsVisible"
    :width="1400"
    title="详情"
    :mask-closable="false"
    :keyboard="false"
    :footer="null"
    destroy-on-close
    class="deviceTabsModal modal-tab-bg"
  >
    <DeviceInfoTabs :page-data="pageData" @change="onChange" />
  </Modal>
  <!-- 演练弹窗 -->
  <Modal
    v-model:open="pushVisible"
    title="演练"
    :width="1400"
    :mask-closable="false"
    :keyboard="false"
    :footer="null"
    centered
    destroy-on-close
    class="deviceTabsModal modal-tab-bg"
  >
    <PushPageTabs :page-data="pageData" />
  </Modal>
  <!-- 日志弹窗 -->
  <Modal
    v-model:open="logVisible"
    title="日志"
    :width="1400"
    :mask-closable="false"
    :keyboard="false"
    :footer="null"
    centered
    class="deviceTabsModal modal-tab-bg"
    destroy-on-close
  >
    <LogView :page-data="pageData" />
  </Modal>
</template>

<script setup lang="tsx">
import { computed, onBeforeUnmount, ref } from 'vue';
import { runModeEnum } from '@/constant';
import { hasPermission } from '@/permission';
import {
  Col,
  FormItemRest,
  Input,
  Modal,
  Row,
  Select,
  Space,
  Table,
  TableColumn,
  Tag,
  TreeSelect,
  message,
} from 'ant-design-vue';
import dayjs from 'dayjs';
import { ProFormProps } from '@/components/ProForm';
import { ProTable, ProTableProps } from '@/components/ProTable/index';
import { useFormModal } from '@/hooks/formModal';
import {
  download,
  isEmptyObject,
  listToEnum,
  listToOption,
  treeToArray,
} from '@/utils/utils';
import { debounce } from '@/utils/utils';
import { getProjectData } from '@/api/config';
import {
  chinaArea,
  deleteTdData,
  deviceDelete,
  deviceRestart,
  disconnectDevice,
  exportDevice,
  getModel,
  listAllDevice,
} from '@/api/device';
import { fetchDictsOfType } from '@/api/dict';
import { getDictType } from '@/api/monitor';
import { saveRecord } from '@/api/notice';
import { getModelInfoById } from '@/api/push';
import { deviceStore } from '../store';
import DeviceInfoTabs from './components/DeviceInfoTabs.vue';
import DeviceTabs from './components/DeviceTabs.vue';
import LogView from './components/LogView.vue';
import PushPageTabs from './components/PushPageTabs.vue';

const { refreshStore, deviceIndustryEnum, getModelOptions } = deviceStore();
const getInit = () => {
  refreshStore.device();
};
getInit();

const params = new URLSearchParams(window.location.search);
const onlineStatus = ref();
if (params.size > 0) {
  onlineStatus.value = params.get('onlineStatus');
}
const pageData: any = ref({});
const deviceTabsVisible = ref(false);
const deviceInfoTabsVisible = ref(false);
const selectRows = ref<any[]>([]);
const isOffline = ref(false);

const rowSelection = computed<ProTableProps['rowSelection']>(() => {
  return {
    onChange(values, selectedRows) {
      selectRows.value = selectedRows;
      isOffline.value = selectedRows.some((item) => {
        return item.onlineStatus == '0';
      });
    },
  };
});
const tableRef = ref();
let searchParams = {};
const _listAllDevice = async (params: any) => {
  const projectId = params.projectId?.join() || undefined;
  const areas = params.areas?.join() || undefined;
  // params.deviceType = params.deviceType_search; //解决dom重构导致columns计算出错问题
  searchParams = { ...params, projectId, areas };
  const res = await listAllDevice(searchParams);
  hideLoading.value = false;
  return res;
};

const hideLoading = ref(false);
let timer = setInterval(() => {
  hideLoading.value = true;
  tableRef.value.search(undefined, false);
}, 30000);
onBeforeUnmount(() => {
  clearTimeout(timer);
});
const sysDeviceModeEnum = ref<Record<string, any>>({});
const sysOnlineStatusEnum = ref<Record<string, any>>({});
const modListEnum = ref<Record<string, any>>({});
const modListOption = ref<Record<string, any>>([]);
const projectData = ref<any>([]);
const chinaAreaData = ref<any>([]);
const init = () => {
  fetchDictsOfType(['sys_device_mode', 'sys_on_line_status']).then(
    (res: any) => {
      const { sys_device_mode, sys_on_line_status } = res.data;
      sysDeviceModeEnum.value = listToEnum(
        sys_device_mode,
        'dictValue',
        'dictLabel',
      );
      sysOnlineStatusEnum.value = listToEnum(
        sys_on_line_status,
        'dictValue',
        'dictLabel',
      );
    },
  );
  // getModel().then((res: any) => {
  //   modListEnum.value = listToEnum(res.data, 'modelId', 'model');
  // });

  getProjectData().then((res: any) => {
    projectData.value = res.data;
    projectData.value.length == 1 && (projectData.value[0].label = '全部');
  });

  chinaArea({}).then((res: any) => {
    chinaAreaData.value = res.data;
  });
};
init();
const changeFormState = async (params: any, formState: any) => {
  if (params.hasOwnProperty('deviceType')) {
    formState.modelId = undefined;
    if (params.deviceType) {
      const res: any = await getModelInfoById({
        type: params.deviceType,
        modelIds: '',
      });
      modListOption.value = listToOption(res.data, 'model', 'modelId');
    } else {
      modListOption.value = [];
    }
  }
};
const columnsOptions = computed(() => {
  return modListOption.value.length
    ? modListOption.value
    : getModelOptions.value;
});

const colorEnum = (value: any) => {
  return value == '1' ? '#87d068' : value == '2' ? 'orange' : '#cd201f';
};

const columns = computed<ProTableProps['columns']>(() => [
  {
    title: '设备序列号',
    dataIndex: 'code',
    // fixed: 'left',
  },
  {
    title: '软件版本',
    dataIndex: 'softwareVersion',
    width: 100,
    hideInSearch: true,
    customRender({ record, text }) {
      return `${record.softwareVersion || ''}${record.versionCode ? `(${record.versionCode})` : ''}`;
    },
    // fixed: 'left',
  },
  {
    title: '软件版本',
    dataIndex: 'version',
    width: 100,
    hideInTable: true,
    customSearchRender(state) {
      return (
        <FormItemRest>
          <Row gutter={8}>
            <Col span={12}>
              <Input
                v-model:value={state.version}
                placeholder='请输入软件版本'
              />
            </Col>
            <Col span={12}>
              <Input
                v-model:value={state.versionCode}
                placeholder='请输入编译版本'
              />
            </Col>
          </Row>
        </FormItemRest>
      );
    },
  },
  {
    title: '编译版本',
    dataIndex: 'versionCode',
    width: 100,
    hideInTable: true,
    hideInSearch: true,
  },
  {
    title: '固件版本',
    dataIndex: 'firmwareVersion',
    // fixed: 'left',
  },
  {
    title: '预警状态',
    dataIndex: 'mqttStatus',
    width: 100,
    customRender({ record, text }) {
      const style = {
        width: '10px',
        height: '10px',
        borderRadius: '50%',
        background: colorEnum(text),
        textAlign: 'center',
      };
      return (
        <div class={'custom_dom'}>
          <div style={style}></div>
        </div>
      );
    },
  },
  {
    title: '文件服务',
    width: 100,
    dataIndex: 'fileStatus',
    customRender({ record, text }) {
      const style = {
        width: '10px',
        height: '10px',
        borderRadius: '50%',
        background: colorEnum(text),
        textAlign: 'center',
      };
      return (
        <div class={'custom_dom'}>
          <div style={style}></div>
        </div>
      );
    },
  },
  {
    title: '运行模式',
    dataIndex: 'runningMode',
    width: 100,
    valueEnum: runModeEnum,
    customRender({ record, text }) {
      return (
        <Tag
          color={
            text == '0'
              ? 'processing'
              : text == '1'
                ? 'success'
                : text == '2'
                  ? 'warning'
                  : 'default'
          }
        >
          {runModeEnum[text as keyof typeof runModeEnum]}
        </Tag>
      );
    },
  },
  // {
  //   title: '设备类型',
  //   dataIndex: 'deviceType_search',
  //   hideInTable: true,
  //   valueEnum: { ...sysDeviceModeEnum.value },
  // },
  {
    title: '设备类型',
    dataIndex: 'deviceType',
    // hideInSearch: true,
    valueEnum: { ...sysDeviceModeEnum.value },
  },
  {
    title: '设备型号',
    dataIndex: 'model',
    hideInSearch: true,
  },
  {
    title: '设备型号',
    dataIndex: 'modelId',
    hideInTable: true,
    customSearchRender(state) {
      return (
        <Select
          v-model:value={state.modelId}
          options={columnsOptions.value}
        ></Select>
      );
    },
  },
  {
    title: '所属项目',
    dataIndex: 'projectId',
    hideInTable: true,
    customSearchRender(state) {
      return (
        <TreeSelect
          v-model:value={state.projectId}
          fieldNames={{ value: 'id' }}
          placeholder='请选择'
          treeData={projectData.value}
          treeCheckable={true}
          maxTagCount={0}
          allowClear={true}
          showCheckedStrategy={TreeSelect.SHOW_ALL}
          maxTagPlaceholder={(omittedValues) => {
            if (omittedValues.length == 1) {
              return omittedValues[0].label;
            } else if (
              omittedValues.length == treeToArray(projectData.value).length
            ) {
              return '全部';
            } else {
              return '多项目';
            }
          }}
        >
          {{
            title: ({ label, type }: any) => {
              return type == '1' ? (
                <span style='color:#bababa'>{label}</span>
              ) : (
                label
              );
            },
          }}
        </TreeSelect>
      );
    },
  },
  {
    title: '所属项目',
    dataIndex: 'projectName',
    hideInSearch: true,
  },
  {
    title: '在线状态',
    dataIndex: 'onlineStatus',
    defaultValue: onlineStatus.value,
    width: 80,
    valueEnum: { ...sysOnlineStatusEnum.value },
    customRender({ text }) {
      return (
        <Tag color={text == 0 ? 'error' : 'success'}>
          {
            sysOnlineStatusEnum.value?.[
              text as keyof typeof sysOnlineStatusEnum.value
            ]
          }
        </Tag>
      );
    },
  },
  {
    title: '上报时间',
    dataIndex: 'reportTime',
    hideInSearch: true,
  },
  {
    title: '状态时长',
    dataIndex: 'statusTime',
    hideInSearch: true,
  },
  {
    title: 'IMEI',
    dataIndex: 'imei',
    hideInTable: true,
  },
  {
    title: '安装单位',
    dataIndex: 'installAddress',
  },
  {
    title: '定位地址',
    dataIndex: 'address',
    hideInTable: !hasPermission('device:locateAddress'),
  },
  {
    title: '行业',
    dataIndex: 'deviceIndustry',
    valueEnum: {
      ...deviceIndustryEnum.value,
    },
  },
  {
    title: '区域搜索',
    dataIndex: 'areas',
    hideInTable: true,
    customSearchRender(state) {
      return (
        <TreeSelect
          v-model:value={state.areas}
          fieldNames={{ value: 'code', label: 'name' }}
          placeholder='请选择'
          showSearch={true}
          treeData={chinaAreaData.value}
          filterTreeNode={filterTreeNode}
          treeCheckable={true}
          maxTagCount={1}
          allowClear={true}
          showCheckedStrategy={TreeSelect.SHOW_ALL}
        ></TreeSelect>
      );
    },
  },
  {
    title: '操作',
    dataIndex: 'operation',
    hideInSearch: true,
    fixed: 'right',
    width: 280,
  },
]);
// 过滤搜索
const filterTreeNode = (inputValue: string, treeNode: any) => {
  return treeNode.name.indexOf(inputValue) > -1;
};
const items = computed<ProFormProps['items']>(() => [
  {
    label: '成功',
    type: 'input',
    field: 'successNum',
  },
  {
    label: '失败',
    type: 'input',
    field: 'failNum',
  },
  {
    label: '详情',
    type: 'input',
    field: 'devices',
    customRender(state) {
      return (
        <Table
          scroll={{ y: 400 }}
          dataSource={state.devices}
          pagination={false}
        >
          <TableColumn dataIndex='code' title='序列号' align='center' />
          <TableColumn dataIndex='status' title='状态' align='center' />
        </Table>
      );
    },
    labelCol: { span: 2 },
    wrapperCol: { span: 22 },
    colProps: {
      span: 24,
    },
  },
]);
const { FormModal, open } = useFormModal({
  size: 'small',
  column: 2,
  formProps: { labelCol: { span: 4 } },
});

const onOperate = (record: any) => {
  pageData.value = record;
  deviceTabsVisible.value = true;
};
const onView = (record: any) => {
  pageData.value = record;
  deviceInfoTabsVisible.value = true;
};

/**
 * 演练
 */
const pushVisible = ref(false);
const onPush = (record: any) => {
  pageData.value = record;
  pushVisible.value = true;
};

/**
 * 日志
 */
const logVisible = ref(false);
const onLog = (record: any) => {
  pageData.value = record;
  logVisible.value = true;
};

const sleep = (cb) => {
  setTimeout(() => {
    cb();
  }, 500);
};

const onDelete = async () => {
  const deviceIds = selectRows.value.map((item) => item.deviceId);
  Modal.confirm({
    title: '系统提示',
    centered: true,
    content: `是否确认删除设备？`,
    onOk: async () => {
      const res = await deviceDelete(deviceIds.join());
      sleep(() => tableRef.value.refresh());
      message.success('操作成功');
      selectRows.value = [];
      saveRecordFn(
        selectRows.value,
        res,
        '删除',
        JSON.stringify({ deviceIds: deviceIds.join() }),
        '/device/',
      );
    },
  });
};
const onExport = async () => {
  let res;
  if (selectRows.value.length) {
    const deviceIds = selectRows.value.map((item) => item.deviceId).join();
    res = await exportDevice({ deviceIds });
  } else {
    res = await exportDevice(searchParams);
  }
  download(
    res as unknown as Blob,
    `设备总览_${dayjs().format('YYYY-MM-DD HH:mm:ss')}.xlsx`,
  );
};

const typeEnum: any = ref();
const dictInit = () => {
  getDictType('device_operate_type').then((res) => {
    typeEnum.value = listToEnum(res.data as any, 'dictLabel', 'dictCode');
  });
};

dictInit();

const handelRestart = debounce(async (type: any, operateButton: string) => {
  const deviceCodes = selectRows.value.map((item) => item.code);
  const res: any = await deviceRestart({ deviceCodes, type });
  saveRecordFn(
    selectRows.value,
    res,
    operateButton,
    JSON.stringify({ deviceCodes, type }),
    '/device/restart',
  );
  open({
    title: (type) => (type === 'info' ? '详情' : '编辑'),
    modalType: 'info',
    defaultValue: { ...res.data },
    serviceApi: Promise.resolve,
    hasEditPermission: false,
  });
  tableRef.value.refresh();
}, 1000);

const saveRecordFn = async (
  data: any,
  res: any,
  operateButton: any,
  requestParam: any,
  operateUri: string,
) => {
  const list = data.map((item: any) => {
    return {
      deviceCode: item.code,
      operateModule: '设备管理/设备总览/列表',
      requestParam,
      status: res.code == 200 ? 1 : 0,
      operateButton,
      operateType: typeEnum.value[operateButton],
      operateUri,
    };
  });
  await saveRecord({ list });
};

const handleConnect = async () => {
  const deviceCodes = selectRows.value.map((item) => item.code);
  const res = await disconnectDevice(deviceCodes.join(','));
  saveRecordFn(
    selectRows.value,
    res,
    '断开',
    JSON.stringify({ deviceCodes: deviceCodes.join(',') }),
    '/device/disconnectDevice/',
  );
  setTimeout(() => {
    tableRef.value.refresh();
  }, 1000);
  message.success('操作成功');
};

const handleClearLog = async () => {
  const codes = selectRows.value.map((item) => item.code);
  Modal.confirm({
    title: '系统提示',
    centered: true,
    content: `是否确认清除日志`,
    onOk: async () => {
      const res = await deleteTdData({ codes });
      sleep(() => tableRef.value.refresh());
      message.success('操作成功');
      saveRecordFn(
        selectRows.value,
        res,
        '清空日志',
        JSON.stringify({ codes }),
        '/device/deleteTdData',
      );
    },
  });
};

const onChange = () => {
  sleep(() => tableRef.value.refresh());
};
</script>
<style>
.ant-select-tree-node-content-wrapper {
  white-space: nowrap !important;
}
/* .ant-select-dropdown {
  width: fit-content !important;
} */

.custom_dom {
  display: flex;
  justify-content: center;
  align-items: center;
}
</style>
